/**
 * 将字符串从 camelCase 转换为 snake_case
 * @param {string} str 
 * @returns {string}
 */
function camelToSnake(str) {
  return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
}

/**
 * 将字符串从 snake_case 转换为 camelCase
 * @param {string} str 
 * @returns {string}
 */
function snakeToCamel(str) {
  return str.replace(/(_\w)/g, matches => matches[1].toUpperCase());
}

/**
 * 递归转换对象的所有键名
 * @param {object} obj 要转换的对象
 * @param {function} keyConverter 键名转换函数
 * @returns {object} 转换后的新对象
 */
function convertKeys(obj, keyConverter) {
  if (Array.isArray(obj)) {
    return obj.map(item => convertKeys(item, keyConverter));
  } else if (obj !== null && typeof obj === 'object') {
    const newObj = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const newKey = keyConverter(key);
        newObj[newKey] = convertKeys(obj[key], keyConverter);
      }
    }
    return newObj;
  }
  return obj;
}

/**
 * 将对象的所有键名从 camelCase 转换为 snake_case（深层递归）
 * @param {object} obj 
 * @returns {object}
 */
export function snakeCase(obj) {
  return convertKeys(obj, camelToSnake);
}

/**
 * 将对象的所有键名从 snake_case 转换为 camelCase（深层递归）
 * @param {object} obj 
 * @returns {object}
 */
export function camelCase(obj) {
  return convertKeys(obj, snakeToCamel);
}